package com.jkgh.tnh.rs {

	import com.jkgh.remedium.*;
	import com.jkgh.remedium.objects.*;
	import com.jkgh.remedium.objects.messages.*;
	import com.jkgh.remedium.objects.messages.ins.*;
	import com.jkgh.remedium.objects.messages.out.*;
	import com.jkgh.remedium.states.*;
	import com.jkgh.remedium.tools.*;

	/**
	 * Some description.
	 * 
	 * @author RS2FGenerator
	 */
	public class TNHSController extends RemediumMethodObject {

		/**
		 * Some description.
		 * 
		 * @param token Some description.
		 * @param intents Some description.
		 * 
		 * @param returner Should return String: Some description.. 
		 */
		public function logIn(token:String, intents:int[], Returner<String> returner):void {
			throw new AbstractMethodNotImplementedError();
		}

		/**
		 * Some description.
		 * 
		 */
		public function logOut():void {
			throw new AbstractMethodNotImplementedError();
		}

		/**
		 * Some description.
		 * 
		 * @param controller Some description.
		 * @param accesses Some description.
		 */
		public function doThings(controller:TNHSController, accesses:TNHAccess[]):void {
			throw new AbstractMethodNotImplementedError();
		}

		// --------------------------------------------------------------------------------

		public function TNHSController(remedium:RemediumSystem, hostID:int = -1, objectID:int = -1, registry:RemediumSystem = null) {
			super(remedium, hostID, objectID, registry);
		}

		override public final function call(remedium:RemediumSystem, message:RemediumInMessage, callID:int, methodID:int, callback:Function):void {
			switch (methodID) {

				case 0:
					RemediumTools.consumeString(remedium, message, function(token0:String):void {
						RemediumTools.consumeIntArray(remedium, message, function(intents0:Vector.<int>):void {
							logIn(token0, intents0, function(r:String):void {
							
								var responder:RemediumC2SStringResponder = new RemediumS2CStringResponder(callID, r);
								responder.produce(remedium);
							});
							callback();
						});
					});
					break;

				case 1:
					logOut();
					callback();
					break;

				case 2:
					remedium.setState(TNHSController.createConsumingState(remedium, message, function(controller2:TNHSController):void {
						remedium.setState(TNHAccess.createVectorConsumingState(remedium, message, function(accesses2:Vector.<TNHAccess>):void {
							doThings(controller2, accesses2);
							callback();
						}));
					}));
					break;
			}
		}

		public static function createConsumingState(message:RemediumInMessage, future:Function):RemediumState {
			return new GatheringState(1, function(remedium:RemediumSystem):void {

				switch (remedium.produceByte()) {

					case RemediumConstants.NULL:
						future(null);
						break;

					case RemediumConstants.HISTORY:
						future(TNHSController(message.fromHistory(remedium.produceInt())));
						break;

					case RemediumConstants.VALUE:
						consumeContent(remedium, message, future);
						break;
				}
			});
		}

		public static function createVectorConsumingState(message:RemediumInMessage, future:Function):RemediumState {
			return new GatheringState(4, function(remedium:RemediumSystem):void {

				var length:int = remedium.produceInt();
				if (length == -1) {
					future(null);
				} else if (length == 0) {
					future(new Vector.<TNHSController>());
				} else {
					var i:int = 0;
					var result:Vector.<TNHSController> = new Vector.<TNHSController>(length, true);
					var onO:Function = function(o:TNHSController):void {
						result[i++] = o;
						if (i == length) {
							future(result);
						} else {
							remedium.setState(createConsumingState(message, onO));
						}
					};
					remedium.setState(createConsumingState(message, onO));
				}
			});
		}

		private static function consumeContent(remedium:RemediumSystem, message:RemediumInMessage, future:Function):void {
			remedium.setState(new GatheringState(8, function(remedium:RemediumSystem):void {

				var hostID:int = remedium.produceInt();
				var objectID:int = remedium.produceInt();

				var methodObject:TNHSController = TNHSController(remedium.getMethodObject(hostID, objectID));
				if (methodObject == null) {
					methodObject = new TNHSControllerRedirector(hostID, objectID, remedium);
				}

				message.toHistory(methodObject);

				future(methodObject);
			});
		}
	}
}

import com.jkgh.remedium.RemediumSystem;
import com.jkgh.remedium.objects.messages.out.RemediumC2SCaller;
import com.jkgh.remedium.tools.RemediumTools;
import com.jkgh.tnh.rs.TNHSController;

class TNHSControllerRedirector extends TNHSController {

	private var remedium:RemediumSystem;

	public function TNHSControllerRedirector(hostID:int, objectID:int, remedium:RemediumSystem) {
		super(null, hostID, objectID, remedium);
		this.host = server.getHost(hostID);
	}

	override public function logIn(token:String, intents:int[], onReturn:Function):void {
		var caller:RemediumC2SCaller = new RemediumC2SCaller(hostID, objectID, 0, remedium.registerCall(onReturn), function():void {
			RemediumTools.produceString(remedium, token);
			RemediumTools.produceIntArray(remedium, intents);
		});
		caller.produce(host.getMachine());
	}

	override public function logOut():void {
		var caller:RemediumC2SCaller = new RemediumC2SCaller(hostID, objectID, 1, 0, function():void {
		});
		caller.produce(host.getMachine());
	}

	override public function doThings(controller:TNHSController, accesses:TNHAccess[]):void {
		var caller:RemediumC2SCaller = new RemediumC2SCaller(hostID, objectID, 2, 0, function():void {
			caller.produceObject(controller, remedium);
			RemediumTools.produceObjectArray(remedium, caller, accesses);
		});
		caller.produce(host.getMachine());
	}
}
